package com.example.agent_intelligent_companion;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

public class BlueToothActivity extends Activity implements OnItemClickListener{
	
	// Database Vaariables
    SQLiteOpenHelper dbHelper;
    SQLiteDatabase database;
	
    //List variables.
    ArrayAdapter<String> listAdapter;
    ListView listView;
    Set<BluetoothDevice> devicesArray;
    ArrayList<String> pairedDevices;
    
    // Variable to hold all the mac addresses to query on.
    List<String> macAddressList;
    
    // Bluetooth variables
    BluetoothAdapter btAdapter;
    ArrayList<BluetoothDevice> devices;
	public static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
	protected static final int SUCCESS_CONNECT = 0;
	protected static final int MESSAGE_READ = 1;
    //IntentFilter filter;
    BroadcastReceiver receiver;
  Handler mHandler = new Handler(){
    	@Override
    	public void handleMessage(Message msg)
    	{
    		super.handleMessage(msg);
    		switch(msg.what)
    		{
    		case SUCCESS_CONNECT:
    			ConnectedThread connectedThread = new ConnectedThread((BluetoothSocket)msg.obj);
    			Toast.makeText(getApplicationContext(), "Connected", 0).show();
    			
    			String s = "succesfully connected";
    			connectedThread.write(s.getBytes());
    			break;
    		case MESSAGE_READ:
    			byte[] readBuf = (byte[])msg.obj;
    			String string = readBuf.toString();
    			Toast.makeText(getApplicationContext(), string, 0);
    		}
    	}
    };

    // Called when the activity is created.
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		//Change the view to the bluetooth activity now that the adapter is set up.
		setContentView(R.layout.activity_blue_tooth);
		
		//Set up the database variables
        dbHelper = new AICDatabase(this);
        database = dbHelper.getWritableDatabase();
		
		// Initialize the bluetooth adapter.
		init();
		
		//btAdapter = BluetoothAdapter.getDefaultAdapter();
		// Check to make sure the adapter is not null.
		if(btAdapter == null)
		{
			Toast.makeText(getApplicationContext(), "Bluetooth Adapter is null", Toast.LENGTH_SHORT).show();
			finish();
		}
		else
		{
			// if it is not null check to see if it is enabled.
			if(!btAdapter.isEnabled())
			{
				turnOnBT();
			}
			
			getPairedDevices();
			startDiscovery();
		}
		
		mHandler = new Handler();
	}

	private void startDiscovery() {
		btAdapter.cancelDiscovery();
		btAdapter.startDiscovery();
	}

	private void turnOnBT() {
		// if it is not enabled. Enable the bluetooth.
		Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
		startActivityForResult(intent, 1);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.blue_tooth, menu);
		return true;
	}

	private void getPairedDevices() {
		devicesArray = btAdapter.getBondedDevices();
		if(devicesArray.size() > 0)
		{
			for(BluetoothDevice device:devicesArray)
			{
				pairedDevices.add(device.getName());
				
			}
		}
	}

	// Initialize the ListView to show profiles (Mac address, Name).
	private void init() {
		// Set up the listview and bluetooth 
		listView = (ListView)findViewById(R.id.listView1);
		listView.setOnItemClickListener(this);
		listAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, 0);
		listView.setAdapter(listAdapter);
		btAdapter = BluetoothAdapter.getDefaultAdapter();
		pairedDevices = new ArrayList<String>();
		
		macAddressList = new ArrayList<String>();
		
		devices = new ArrayList<BluetoothDevice>();
		receiver = new BroadcastReceiver(){
			@Override
			public void onReceive(Context context, Intent intent){
				String action = intent.getAction();
				
				// if a bluetooth device is found add it to the adapter.
				if(BluetoothDevice.ACTION_FOUND.equals(action))
				{
					// Get the device
					BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
					// Add it to the devices list.
					devices.add(device);
										
					// Add the device name and mac address to the list.
					//listAdapter.add(device.getName() + "\n" + device.getAddress());
					macAddressList.add(device.getAddress());
					
					// TODO: query the database for the name and mac address.
				}
				else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action))
				{
					//btAdapter.cancelDiscovery();
					Toast.makeText(getApplicationContext(), "Finished scanning", 0).show();
					// Finished Scanning clear list adapter.
					listAdapter.clear();
					
					if(macAddressList.size() > 0)
					{
						// Check for mac addresses found in the last scan.
						CheckDB(macAddressList);
						macAddressList = new ArrayList<String>();
					}
					btAdapter.startDiscovery();
				}
			}
		};
		
		// register the receiver.
		IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
		registerReceiver(receiver, filter);
//		filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
//		registerReceiver(receiver, filter);
		filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
		registerReceiver(receiver, filter);
//		filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
	}
	
	public void CheckDB(List<String> macAdd)
	{		
		String query = "SELECT mac_address FROM users WHERE mac_address IN (";
		String inStmt = "";
		
		for(int i = 0; i < macAdd.size(); i++)
		{
			inStmt = inStmt + "'" + macAdd.get(i).toString() + "', ";
		}
		
		inStmt = (String) inStmt.subSequence(0, inStmt.length() - 2);
		
		query = query + inStmt + ")";
		
		Cursor c = database.rawQuery(query, null);
		
		if(c.moveToFirst())
		{
			while (c.isAfterLast() == false)
			{
				listAdapter.add(c.getString(0));
				c.moveToNext();
			}
		}
	}
	
	@Override
	protected void onPause()
	{
		// on pause unregister the receiver.
		super.onPause();
		unregisterReceiver(receiver);
		Toast.makeText(getApplicationContext(), "Paused", 0).show();
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data)
	{
		super.onActivityResult(requestCode, resultCode, data);
		if(resultCode == RESULT_CANCELED)
		{
			Toast.makeText(getApplicationContext(), "Bluetooth must be enabled to continue.", Toast.LENGTH_SHORT).show();
			
		}
	}

	@Override
	public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
		// TODO Auto-generated method stub
		if(btAdapter.isDiscovering())
		{
			btAdapter.cancelDiscovery();
		}
		if(listAdapter.getItem(arg2).contains("(Paired)"))
		{
			BluetoothDevice selectedDevice = devices.get(arg2);
			ConnectThread connect = new ConnectThread(selectedDevice);
			connect.start();
		}
		else
		{
			Toast.makeText(getApplicationContext(), "device is not paired", 0).show();
		}
	}
	
	private class ConnectThread extends Thread
	{
		private final BluetoothSocket mmSocket;
		private final BluetoothDevice mmDevice;
		
	    public ConnectThread(BluetoothDevice device) {
	        // Use a temporary object that is later assigned to mmSocket,
	        // because mmSocket is final
	        BluetoothSocket tmp = null;
	        mmDevice = device;
	 
	        // Get a BluetoothSocket to connect with the given BluetoothDevice
	        try {
	            // MY_UUID is the app's UUID string, also used by the server code
	            tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
	        } catch (IOException e) { }
	        mmSocket = tmp;
	    }
		
		public void run()
		{
			btAdapter.cancelDiscovery();
			
			try
			{
				mmSocket.connect();
			}
			catch (IOException connectException)
			{
				try
				{
					mmSocket.close();
				}
				catch(IOException closeException) {}
				return;
			}
			
			manageConnectedSocket(mmSocket);
			mHandler.obtainMessage(SUCCESS_CONNECT, mmSocket).sendToTarget();
		}
		
		private void manageConnectedSocket(BluetoothSocket mySocket2)
		{
			
		}
		
		public void cancel()
		{
			try
			{
				mmSocket.close();
			}
			catch(IOException e) {}
		}
		
	}
	
	private class ConnectedThread extends Thread {
	    private final BluetoothSocket mmSocket;
	    private final InputStream mmInStream;
	    private final OutputStream mmOutStream;
	 
	    public ConnectedThread(BluetoothSocket socket) {
	        mmSocket = socket;
	        InputStream tmpIn = null;
	        OutputStream tmpOut = null;
	 
	        // Get the input and output streams, using temp objects because
	        // member streams are final
	        try {
	            tmpIn = socket.getInputStream();
	            tmpOut = socket.getOutputStream();
	        } catch (IOException e) { }
	 
	        mmInStream = tmpIn;
	        mmOutStream = tmpOut;
	    }
	 
	    public void run() {
	        byte[] buffer;  // buffer store for the stream
	        int bytes; // bytes returned from read()
	 
	        // Keep listening to the InputStream until an exception occurs
	        while (true) {
	            try {
	                // Read from the InputStream
	                buffer = new byte[1024];
	                bytes = mmInStream.read(buffer);
	                // Send the obtained bytes to the UI activity
	                mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
	                        .sendToTarget();
	            } catch (IOException e) {
	                break;
	            }
	        }
	    }
	 
	    /* Call this from the main activity to send data to the remote device */
	    public void write(byte[] bytes) {
	        try {
	            mmOutStream.write(bytes);
	        } catch (IOException e) { }
	    }
	 
	    /* Call this from the main activity to shutdown the connection */
	    public void cancel() {
	        try {
	            mmSocket.close();
	        } catch (IOException e) { }
	    }
	}
}
